1 Preamble

This document has been created using Rmarkdown, for the example of the Movement Ecology Course proposed to the Center for Wildlife Studies. This document contains all needed annotations to reproduce the practice section of the class. Rmarkdown is useful for creating codes with annotations, for reproducibility, for writing reports including plots and results from R, for creating tutorials, as in this case.

2 Installing and Loading packages

Creating a list of the packages to load allows to install, then to load, all the packages at once, using the function sapply.

# create packages list
packages <- list("plyr","dplyr","magrittr","lubridate","sp","sf","mapview","ggplot2")

# install the packages
# sapply(packages, install.packages, character = TRUE)

# load the packages
sapply(packages, require, character = TRUE)

3 Load and explore data

Load the data I have shared with you. This dataset contains GPS locations of 4 individual barren-ground caribou (Rangifer tarandus groenlendicus and granti) from a population in Canada. Barren-ground caribou is the migratory ecotype of caribou and travels hundreds of kilometers between their winter and summer ranges.

# change the path accordingly
caribou <- read.csv("C://Users/ohcourio/Documents/Applications/2022/Center for wildlife studies/CourseExample/caribou.csv")

Now that we loaded the data, we can see what it looks like. Let’s see the dimensions of the data frame, the name of the columns and the top rows.

# dimensions
dim(caribou)
## [1] 18074     6
# columns names
names(caribou)
## [1] "ID"   "sex"  "Time" "Year" "Lon"  "Lat"
# top rows
head(caribou)
##       ID sex           Time Year       Lon      Lat
## 1 Dancer   f  4/1/2002 0:00 2002 -133.8427 62.77028
## 2 Dancer   f  4/1/2002 8:00 2002 -133.8394 62.76716
## 3 Dancer   f 4/1/2002 16:00 2002 -133.8453 62.77767
## 4 Dancer   f  4/2/2002 0:00 2002 -133.8643 62.80010
## 5 Dancer   f  4/2/2002 8:00 2002 -133.8621 62.79918
## 6 Dancer   f 4/2/2002 16:00 2002 -133.8625 62.80007

The data has 18074 rows and 6 columns: - The unique identifier of the animal - The sex of the animal - The Date and Time of each fix (i.e., GPS location) - The Longitude and Latitude of the fix

We can also look at the structure of the data (the class of each column of the data frame), using the str function.

# Look at the structure of the data
str(caribou)
## 'data.frame':    18074 obs. of  6 variables:
##  $ ID  : chr  "Dancer" "Dancer" "Dancer" "Dancer" ...
##  $ sex : chr  "f" "f" "f" "f" ...
##  $ Time: chr  "4/1/2002 0:00" "4/1/2002 8:00" "4/1/2002 16:00" "4/2/2002 0:00" ...
##  $ Year: int  2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 ...
##  $ Lon : num  -134 -134 -134 -134 -134 ...
##  $ Lat : num  62.8 62.8 62.8 62.8 62.8 ...

This function gives the dimensions of the data frame, the name and the class of the columns.

4 Process data

We see that the ID, sex and Time are characters. For an easy manipulation and visualization, it is easier if ID and sex are factors. The characteristic of movement data is that they are spatio-temporal. This means that they are time series and thus that each GPS location (fix) has an associated Date and Time. Since R is able to handle Date and Times as such, we will convert the Date and Time as Date-time using the as.POSIXct function.

The Time now looks like:

# check the time format
caribou$Time[1]
## [1] "4/1/2002 0:00"

When transforming the Time as a Date-time, we will need to specify the time zone, which is “utc” and the format in as.POSIXct. To know what format it is, by looking at the strptime help.

?strptime

In the Details, you can find the format to specify. In our case, the Time is in the format “month/day/year hour:minute” as follow: “m/d/yyyy h:mm”. According to strptime, the format is thus: “%m/%d/%Y %H:%M”.

plyr and magrittr are useful for rearranging data frames in one line of code instead of several lines. Below is how we would do without using plyr and magrittr.

# create a new data frame to not overwrite the raw data in case of error
caribou2 <- caribou

# set ID and sex as factors and Time as Date-time without using plyr and magrittr
caribou2$ID <- as.factor(caribou2$ID)
caribou2$sex <- as.factor(caribou2$sex)
caribou2$Time <- as.POSIXct(as.character(caribou2$Time), format="%m/%d/%Y %H:%M", tz = "utc")
head(caribou2)
##       ID sex                Time Year       Lon      Lat
## 1 Dancer   f 2002-04-01 00:00:00 2002 -133.8427 62.77028
## 2 Dancer   f 2002-04-01 08:00:00 2002 -133.8394 62.76716
## 3 Dancer   f 2002-04-01 16:00:00 2002 -133.8453 62.77767
## 4 Dancer   f 2002-04-02 00:00:00 2002 -133.8643 62.80010
## 5 Dancer   f 2002-04-02 08:00:00 2002 -133.8621 62.79918
## 6 Dancer   f 2002-04-02 16:00:00 2002 -133.8625 62.80007

When using magrittr and plyr, everything can be done in one line of code. The pipes “%>%” allow to specify that we are applying a function to the object before the pipes. The function mutate allows to change columns of a data frame all at once.

# create a new data frame to not overwrite the raw data in case of error and set ID and sex as factors and Time as Date-time in one line
caribou2 <- caribou %>% mutate(ID = as.factor(ID),
                               sex = as.factor(sex),
                               Time = as.POSIXct(Time, format = "%m/%d/%Y %H:%M", tz = "utc"))
head(caribou2)
##       ID sex                Time Year       Lon      Lat
## 1 Dancer   f 2002-04-01 00:00:00 2002 -133.8427 62.77028
## 2 Dancer   f 2002-04-01 08:00:00 2002 -133.8394 62.76716
## 3 Dancer   f 2002-04-01 16:00:00 2002 -133.8453 62.77767
## 4 Dancer   f 2002-04-02 00:00:00 2002 -133.8643 62.80010
## 5 Dancer   f 2002-04-02 08:00:00 2002 -133.8621 62.79918
## 6 Dancer   f 2002-04-02 16:00:00 2002 -133.8625 62.80007

Now we can look at the number of individuals, their sex and the monitoring.

# Individuals
levels(caribou2$ID)
## [1] "Comet"   "Dancer"  "Prancer" "Vixen"
# sex
levels(caribou2$sex)
## [1] "f" "m"
# number of observation per individual and sex
table(caribou2$ID, caribou2$sex)
##          
##              f    m
##   Comet      0 4360
##   Dancer  8563    0
##   Prancer    0 2631
##   Vixen   2520    0
# monitoring
by(caribou2$Time, caribou2$ID, range)
## caribou2$ID: Comet
## [1] "2006-04-01 00:00:00 UTC" "2008-04-01 16:00:00 UTC"
## ------------------------------------------------------------ 
## caribou2$ID: Dancer
## [1] "2002-04-01 UTC" "2005-03-11 UTC"
## ------------------------------------------------------------ 
## caribou2$ID: Prancer
## [1] "2014-04-04 00:01:00 UTC" "2016-09-02 08:00:00 UTC"
## ------------------------------------------------------------ 
## caribou2$ID: Vixen
## [1] "2007-04-01 00:00:00 UTC" "2009-08-01 16:00:00 UTC"

We see that all individuals have several years of monitoring and that Comet and Vixen have overlapping monitoring between 2007-04-01 and 2008-04-01.

It is very important when manipulating spatial data and time series to ALWAYS order by Individual and Time.

caribou2 <- caribou2[order(caribou2$ID, caribou2$Time),]

5 Visualizing data

Caribou is a migrating species, let’s look at the latitude of individuals through time, using ggplot.

ggplot(data = caribou2, aes(x=Time, y=Lat)) + geom_line(aes(color = ID)) + facet_wrap(~ID, scales="free")

To visualize movement data, we can plot the data using ggplot2 for example.

# Plot the GPS data using ggplot2
ggplot(data=caribou2, aes(x=Lon, y=Lat)) + geom_point()

We see all the GPS locations together, we should add some colour depending on the individual.

# Plot the GPS data using ggplot2, each color represents an individual
ggplot(data=caribou2, aes(x=Lon, y=Lat)) + geom_point(aes(color=ID))

It is better. We can also see the trajectories by plotting lines.

# Plot trajectories using ggplot2, each color represents an individual
ggplot(data=caribou2, aes(x=Lon, y=Lat)) + geom_path(aes(color=ID))

We can also see where individuals started and where they finished.

# first we add a vector of integers from the first to the last location for each individual
caribou2 <- caribou2 %>% group_by(ID) %>% mutate(timeSeq = seq(1,length(Time),1)) %>% ungroup %>% as.data.frame
head(caribou2)
##      ID sex                Time Year       Lon      Lat timeSeq
## 1 Comet   m 2006-04-01 00:00:00 2006 -130.9916 63.97680       1
## 2 Comet   m 2006-04-01 01:00:00 2006 -130.9920 63.97703       2
## 3 Comet   m 2006-04-01 02:00:00 2006 -130.9928 63.98008       3
## 4 Comet   m 2006-04-01 03:00:00 2006 -130.9918 63.98152       4
## 5 Comet   m 2006-04-01 04:00:00 2006 -130.9900 63.98217       5
## 6 Comet   m 2006-04-01 05:00:00 2006 -130.9901 63.98215       6
# verify it did it by individual
by(caribou2$timeSeq, caribou2$ID, range)
## caribou2$ID: Comet
## [1]    1 4360
## ------------------------------------------------------------ 
## caribou2$ID: Dancer
## [1]    1 8563
## ------------------------------------------------------------ 
## caribou2$ID: Prancer
## [1]    1 2631
## ------------------------------------------------------------ 
## caribou2$ID: Vixen
## [1]    1 2520

Take the example of Vixen

# Plot trajectory of Vixen, with the a gradient of color depending on the time series
ggplot(data=caribou2 %>% subset(ID == "Vixen"), aes(x=Lon, y=Lat)) + geom_path(aes(color=timeSeq))

We see where Vixen started her journey and where the collars dropped off.

What would be very interesting now would be to see where they are (on a map). mapview is a very useful package which creates interactive maps. However, to use mapview, the data needs to be spatial data with a projection.

6 Spatial data and projections

There are several ways to manipulate spatial objects. Here we are using simple features (or sf objects), which are object in the real world that are viewable on a computer thanks to the presence of a spatial geometry (coordinates of the object).

6.1 Simple Features

Lets transform our data frame into a simple feature, using the package sf. Before doing so, it is important to know what is the spatial reference system of the GPS locations or coordinate system! For the caribou data, the coordinates are referenced in the latest version of the World Geodetic System (WGS), which is WGS84. To know what your coordinate system is you can go to epsg.io, which references most of coordinate systems. Type World Geodetic System 84 and get the corresponding epsg or crs, which is 4326.

# transform data into simple feature
caribou.sf <- caribou2 %>% st_as_sf(coords=c("Lon","Lat"), crs = 4326)

Now that we have sf object, let’s see what it looks like.

# first rows of the sf object
head(caribou.sf)
## Simple feature collection with 6 features and 5 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
# structure of the sf object
str(caribou.sf)
## Classes 'sf' and 'data.frame':   18074 obs. of  6 variables:
##  $ ID      : Factor w/ 4 levels "Comet","Dancer",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ sex     : Factor w/ 2 levels "f","m": 2 2 2 2 2 2 2 2 2 2 ...
##  $ Time    : POSIXct, format: "2006-04-01 00:00:00" "2006-04-01 01:00:00" ...
##  $ Year    : int  2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
##  $ timeSeq : num  1 2 3 4 5 6 7 8 9 10 ...
##  $ geometry:sfc_POINT of length 18074; first list element:  'XY' num  -131 64
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA
##   ..- attr(*, "names")= chr [1:5] "ID" "sex" "Time" "Year" ...

The object is both a simple feature (sf), containing 18074 features (the rows in our data frame), but not the same columns (fields). What happened is that the Lon,Lat coordinates have been used to create the geometry column (where on Earth is the feature). To get the coordinates from sf objects, we use the function st_coordinates.

# get coordinates from an sf object
head(st_coordinates(caribou.sf)) # for example st_coordinates(caribous.sf)[,1] will give the x or Longitude
##           X        Y
## 1 -130.9916 63.97680
## 2 -130.9920 63.97703
## 3 -130.9928 63.98008
## 4 -130.9918 63.98152
## 5 -130.9900 63.98217
## 6 -130.9901 63.98215
# add the coordinates to the sf object
caribou.sf <- caribou.sf %>% mutate(Lon = st_coordinates(.)[,1], Lat = st_coordinates(.)[,2])
head(caribou.sf)
## Simple feature collection with 6 features and 7 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
##         Lon      Lat
## 1 -130.9916 63.97680
## 2 -130.9920 63.97703
## 3 -130.9928 63.98008
## 4 -130.9918 63.98152
## 5 -130.9900 63.98217
## 6 -130.9901 63.98215

6.2 Visualization

We can now visualize our data on a map using mapview.

# visualize sf object, adding different color for each individual
mapview(caribou.sf, zcol = "ID")

This map is interactive, in your viewer, you can Zoom in and out, click on a points to have the information linked to that point, etc.

6.3 Create lines

Simple Features are very convenient to create lines, instead of having points. We will now create one line per individual and visualize it, using the functions group_by, summarize and st_cast, which will cast points to lines, by grouping and summarizing per individual.

# create lines of the trajectory of each individual by grouping and summarizing per individual
caribou.lines <- caribou.sf %>% group_by(ID) %>%
  summarize(do_union=FALSE) %>% st_cast("LINESTRING")

# visualize the lines adding a different color for each individual
mapview(caribou.lines, zcol = "ID")

But can we add points with the start and end of the trajectory for each individual? We just need to get the first and last location for each individual from the points object (caribou.sf) and add it to mapview.

# apply a function per ID that keeps the first and last row for each individual, then reproject
StartEnd.sf <- caribou.sf %>% 
  dlply(.(ID), function(sf){rbind(sf[1,] %>% mutate(trajectory = "Start"), sf[dim(sf)[1],] %>% mutate(trajectory = "End"))}) %>% ldply %>% st_as_sf(crs=4326) %>% mutate(trajectory = factor(trajectory, levels = c("Start", "End")))


# see the first rows
head(StartEnd.sf)
## Simple feature collection with 6 features and 8 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -133.8427 ymin: 62.77028 xmax: -130.0881 ymax: 64.18784
## Geodetic CRS:  WGS 84
##        ID sex                Time Year timeSeq       Lon      Lat trajectory
## 1   Comet   m 2006-04-01 00:00:00 2006       1 -130.9916 63.97680      Start
## 2   Comet   m 2008-04-01 16:00:00 2008    4360 -131.3025 64.02808        End
## 3  Dancer   f 2002-04-01 00:00:00 2002       1 -133.8427 62.77028      Start
## 4  Dancer   f 2005-03-11 00:00:00 2005    8563 -132.5513 63.00278        End
## 5 Prancer   m 2014-04-04 00:01:00 2014       1 -130.1054 63.14468      Start
## 6 Prancer   m 2016-09-02 08:00:00 2016    2631 -130.0881 64.18784        End
##                     geometry
## 1  POINT (-130.9916 63.9768)
## 2 POINT (-131.3025 64.02808)
## 3 POINT (-133.8427 62.77028)
## 4 POINT (-132.5513 63.00278)
## 5 POINT (-130.1054 63.14468)
## 6 POINT (-130.0881 64.18784)
# visualize the lines adding a different color for each individual + the start and end of the trajectory for each individual
mapview(caribou.lines, zcol = "ID", layer.name="ID") + mapview(StartEnd.sf, zcol="trajectory", col.regions=c("darkgreen","darkorange3"), layer.name="Trajectory")

7 Manipulating Date and Time

Since movement data are time series, let’s see how to manipulate Date and Time. The package lubridate offers several functions to deal with dates and times. We can extract the hour, the day of year, the week, the month or the year for example. This will further allow to filter the data or to summarize data.

7.1 Extract day of year

Since our individuals are not monitored on the same years, it might be interesting to compare movement patterns throughout the year. To do so, we need to create a column day of year to not consider the year.

# create doy (day of year column)
caribou.sf <- caribou.sf %>% mutate(doy = yday(Time))

# see first rows
head(caribou.sf)
## Simple feature collection with 6 features and 8 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
##         Lon      Lat doy
## 1 -130.9916 63.97680  91
## 2 -130.9920 63.97703  91
## 3 -130.9928 63.98008  91
## 4 -130.9918 63.98152  91
## 5 -130.9900 63.98217  91
## 6 -130.9901 63.98215  91

7.2 Extract the month

We can also extract the month.

# create doy (day of year column)
caribou.sf <- caribou.sf %>% mutate(month = month(Time))

# see first rows
head(caribou.sf)
## Simple feature collection with 6 features and 9 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
##         Lon      Lat doy month
## 1 -130.9916 63.97680  91     4
## 2 -130.9920 63.97703  91     4
## 3 -130.9928 63.98008  91     4
## 4 -130.9918 63.98152  91     4
## 5 -130.9900 63.98217  91     4
## 6 -130.9901 63.98215  91     4

7.3 Extract the week

# create doy (day of year column)
caribou.sf <- caribou.sf %>% mutate(week = week(Time))

# see first rows
head(caribou.sf)
## Simple feature collection with 6 features and 10 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
##         Lon      Lat doy month week
## 1 -130.9916 63.97680  91     4   13
## 2 -130.9920 63.97703  91     4   13
## 3 -130.9928 63.98008  91     4   13
## 4 -130.9918 63.98152  91     4   13
## 5 -130.9900 63.98217  91     4   13
## 6 -130.9901 63.98215  91     4   13

7.4 Extract the year

Extract the year, but also the month and the day of year in one line of code.

# create doy (day of year column)
caribou.sf <- caribou.sf %>% mutate(doy = yday(Time), month = month(Time), week = week(Time), year=year(Time))

# see first rows
head(caribou.sf)
## Simple feature collection with 6 features and 11 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -130.9928 ymin: 63.9768 xmax: -130.99 ymax: 63.98217
## Geodetic CRS:  WGS 84
##      ID sex                Time Year timeSeq                   geometry
## 1 Comet   m 2006-04-01 00:00:00 2006       1  POINT (-130.9916 63.9768)
## 2 Comet   m 2006-04-01 01:00:00 2006       2  POINT (-130.992 63.97703)
## 3 Comet   m 2006-04-01 02:00:00 2006       3 POINT (-130.9928 63.98008)
## 4 Comet   m 2006-04-01 03:00:00 2006       4 POINT (-130.9918 63.98152)
## 5 Comet   m 2006-04-01 04:00:00 2006       5   POINT (-130.99 63.98217)
## 6 Comet   m 2006-04-01 05:00:00 2006       6 POINT (-130.9901 63.98215)
##         Lon      Lat doy month week year
## 1 -130.9916 63.97680  91     4   13 2006
## 2 -130.9920 63.97703  91     4   13 2006
## 3 -130.9928 63.98008  91     4   13 2006
## 4 -130.9918 63.98152  91     4   13 2006
## 5 -130.9900 63.98217  91     4   13 2006
## 6 -130.9901 63.98215  91     4   13 2006

7.5 Filter and summarize data

We would like to keep only the summer locations (between July 1 and August 31) for each individual and each year.

# Day of year for July 1 during a leap year and non leap year
yday("2012-07-01"); yday("2011-07-01")
## [1] 183
## [1] 182
# Day of year for August 31 during a leap year and non leap year
yday("2012-08-31"); yday("2011-08-31")
## [1] 244
## [1] 243
# filter data according to the dates above depending if it is a leap year or not
summer.sf <- caribou.sf %>% subset((leap_year(year) & doy >= 183 & doy <= 244) |
                                        (leap_year(year) == FALSE & doy >= 182 & doy <= 243))

head(summer.sf)
## Simple feature collection with 6 features and 11 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -131.5066 ymin: 65.24346 xmax: -131.2824 ymax: 65.37193
## Geodetic CRS:  WGS 84
##         ID sex                Time Year timeSeq                   geometry
## 1011 Comet   m 2006-07-01 00:00:00 2006    1011 POINT (-131.4573 65.37193)
## 1012 Comet   m 2006-07-01 08:01:00 2006    1012  POINT (-131.5066 65.3531)
## 1013 Comet   m 2006-07-01 16:00:00 2006    1013 POINT (-131.4717 65.29286)
## 1014 Comet   m 2006-07-02 00:00:00 2006    1014 POINT (-131.4633 65.27621)
## 1015 Comet   m 2006-07-02 08:00:00 2006    1015 POINT (-131.3186 65.26868)
## 1016 Comet   m 2006-07-02 16:00:00 2006    1016 POINT (-131.2824 65.24345)
##            Lon      Lat doy month week year
## 1011 -131.4573 65.37193 182     7   26 2006
## 1012 -131.5066 65.35310 182     7   26 2006
## 1013 -131.4717 65.29286 182     7   26 2006
## 1014 -131.4633 65.27621 183     7   27 2006
## 1015 -131.3186 65.26868 183     7   27 2006
## 1016 -131.2824 65.24345 183     7   27 2006

You have filtered your data! Let’s now take the average location of individuals for each week and year during summer.

# get the average location for each individual, year and week during the summer months
summerweeks.sf <- summer.sf %>% group_by(ID, year, week) %>% summarize(Lon = mean(Lon), Lat = mean(Lat)) %>% ungroup %>% as.data.frame %>% st_as_sf(coords = c("Lon", "Lat"), crs=4326)
## `summarise()` has grouped output by 'ID', 'year'. You can override using the
## `.groups` argument.
# order per ID, year and week
summerweeks.sf <- summerweeks.sf[order(summerweeks.sf$ID, summerweeks.sf$year, summerweeks.sf$week),]

# get lines joining weekly location during summer for each individual and each year
summerweeks.lines <- summerweeks.sf %>% group_by(ID, year) %>%
  summarize(do_union=FALSE) %>% st_cast("LINESTRING") %>% mutate(ID_Year = paste(ID, year, sep = "_"))
## `summarise()` has grouped output by 'ID'. You can override using the `.groups`
## argument.
# map it with mapview
mapview(summerweeks.lines, zcol = "ID_Year")

Good job! Can you see all the possibilities?

Let’s do an exercise…

8 Exercise

Using what you have learnt during this class, create a map of the yearly individual trajectories during the spring migration. Spring migration is known to occur between the beginning of April and the end of May for caribou. This map should be interactive and present annual trajectories of the individuals, with a different color for each individual and year. Create an annotated R script which explain each step, to allow someone else to reproduce your analysis. Once you are done, send your code and potential data to be used at .